package com.realdolmen.whiteyellowcross.appengine.datastore;

import static com.google.appengine.api.datastore.FetchOptions.Builder.withLimit;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.EmbeddedEntity;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.CompositeFilterOperator;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Query.FilterPredicate;
import com.realdolmen.whiteyellowcross.datastore.WaitWorkShiftDayPlanDataStore;
import com.realdolmen.whiteyellowcross.model.Personel;
import com.realdolmen.whiteyellowcross.model.WaitWorkShift;
import com.realdolmen.whiteyellowcross.model.WaitWorkShiftDayPlan;

public class WaitWorkShiftDayPlanAppEngineDataStore implements
		WaitWorkShiftDayPlanDataStore {

	private DatastoreService datastoreService;
	private static WaitWorkShiftDayPlanDataStore waitWorkShiftPlanDataStore;

	private WaitWorkShiftDayPlanAppEngineDataStore(
			DatastoreService datastoreService) {
		this.datastoreService = datastoreService;
	}

	public static WaitWorkShiftDayPlanDataStore getInstance(
			DatastoreService datastoreService) {
		if (waitWorkShiftPlanDataStore == null) {
			synchronized (WaitWorkShiftDayPlanAppEngineDataStore.class) {
				if (waitWorkShiftPlanDataStore == null) {
					waitWorkShiftPlanDataStore = new WaitWorkShiftDayPlanAppEngineDataStore(
							datastoreService);
				}

			}
		}
		return waitWorkShiftPlanDataStore;
	}

	private WaitWorkShiftDayPlan transFormEntityToWaitWorkShiftDayPlan(
			Entity entity) {
		WaitWorkShiftDayPlan waitWorkShiftDayPlan = null;
		Personel personel = null;
		WaitWorkShift waitWorkShift = null;
		if (entity != null) {

			EmbeddedEntity embeddedPersonel = (EmbeddedEntity) entity
					.getProperty("personel");
			Key personelKey = embeddedPersonel.getKey();

			Entity personelEntity = new Entity(personelKey);
			personelEntity.setPropertiesFrom(embeddedPersonel);

			personel = transFormEntityToPersonel(personelEntity);

			EmbeddedEntity embeddedWorkShift = (EmbeddedEntity) entity
					.getProperty("workshift");
			Key workShiftKey = embeddedWorkShift.getKey();

			Entity workShiftEntity = new Entity(workShiftKey);
			workShiftEntity.setPropertiesFrom(embeddedWorkShift);

			waitWorkShift = transFormEntityToWaitWorkShift(workShiftEntity);

			waitWorkShiftDayPlan = new WaitWorkShiftDayPlan(
					KeyFactory.keyToString(entity.getKey()), waitWorkShift,
					personel);

		}
		return waitWorkShiftDayPlan;
	}

	private Personel transFormEntityToPersonel(Entity entity) {
		Personel personel = null;
		if (entity != null) {
			personel = new Personel((String) entity.getProperty("name"));
			personel.setId(KeyFactory.keyToString(entity.getKey()));
		}
		return personel;
	}

	private WaitWorkShift transFormEntityToWaitWorkShift(Entity entity) {
		WaitWorkShift waitWorkShift = null;
		if (entity != null) {
			waitWorkShift = new WaitWorkShift(
					(String) entity.getProperty("name"),
					(Date) entity.getProperty("from"),
					(Date) entity.getProperty("to"),
					(Long) entity.getProperty("hours"));
			waitWorkShift.setId(KeyFactory.keyToString(entity.getKey()));
		}
		return waitWorkShift;
	}



    @Override
    public String insertWaitWorkShiftDayPlan(Date waitWorkShiftDay, String personelId, String workShiftId) {
        Entity waitWorkShiftDayPlan = new Entity(
                WaitWorkShiftDayPlan.class.getCanonicalName());

        EmbeddedEntity embeddedPersonel = new EmbeddedEntity();

        Key personelKey = KeyFactory.stringToKey(personelId);
        Entity personelEntity = new Entity(personelKey);

        embeddedPersonel.setKey(personelKey);
        embeddedPersonel.setPropertiesFrom(personelEntity);

        EmbeddedEntity embeddedWorkShift = new EmbeddedEntity();

        Key workShiftKey = KeyFactory.stringToKey(workShiftId);
        Entity workShiftEntity = new Entity(workShiftKey);

        embeddedWorkShift.setKey(workShiftKey);
        embeddedPersonel.setPropertiesFrom(workShiftEntity);

        waitWorkShiftDayPlan.setProperty("date", waitWorkShiftDay);
        waitWorkShiftDayPlan.setProperty("personel", embeddedPersonel);
        waitWorkShiftDayPlan.setProperty("workshift", embeddedWorkShift);

        Key waitWorkShiftDayPlanKey = datastoreService.put(waitWorkShiftDayPlan);

        return KeyFactory.keyToString(waitWorkShiftDayPlanKey);
    }

    @Override
    public List<WaitWorkShiftDayPlan> getWaitWorkShiftDayPlan(Date waitWorkShiftDay) {
        Query query = new Query(WaitWorkShiftDayPlan.class.getCanonicalName());

        Filter fromDateFilter = new FilterPredicate("date",
                FilterOperator.GREATER_THAN_OR_EQUAL, waitWorkShiftDay);

        Filter toDateFilter = new FilterPredicate("date",
                FilterOperator.LESS_THAN_OR_EQUAL, waitWorkShiftDay);

        // Use CompositeFilter to combine multiple filters
        Filter dateRangeFilter = CompositeFilterOperator.and(fromDateFilter,
                toDateFilter);

        query.setFilter(dateRangeFilter);
        PreparedQuery preparedQuery = datastoreService.prepare(query);
        List<Entity> entityList = preparedQuery.asList(withLimit(100));
        List<WaitWorkShiftDayPlan> waitWorkShiftDayPlanList = new ArrayList<WaitWorkShiftDayPlan>();
        for (Entity entity : entityList) {
            waitWorkShiftDayPlanList
                    .add(transFormEntityToWaitWorkShiftDayPlan(entity));
        }
        return waitWorkShiftDayPlanList;
    }

   	@Override
	public boolean updateWaitWorkShiftDayPlan(String waitWorkShiftDayPlanId, String personelId) {

		EmbeddedEntity embeddedPersonel = new EmbeddedEntity();

		Key personelKey = KeyFactory.stringToKey(personelId);
		Entity personelEntity = new Entity(personelKey);

		embeddedPersonel.setKey(personelKey);
		embeddedPersonel.setPropertiesFrom(personelEntity);

		Key waitWorkShiftDayPlanKey = KeyFactory.stringToKey(waitWorkShiftDayPlanId);
		Entity workShiftEntity = new Entity(waitWorkShiftDayPlanKey);
		workShiftEntity.setProperty("personel", embeddedPersonel);
		datastoreService.put(workShiftEntity);
		return false;
	}
}
